package com.michale.framework.config.async.config;

import com.michale.common.properties.ThreadProperties;
import com.michale.common.utils.async.ThreadUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.Resource;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author Michale
 * @apiNote 配置线程池
 */
@Configuration
public class ThreadPoolConfig {

    @Resource
    private ThreadProperties threadProperties;

    /**
     * 创建线程池
     *
     * @param
     * @return
     */
    @Bean("threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        //核心线程池大小
        threadPoolTaskExecutor.setMaxPoolSize(threadProperties.getMaxPoolSize());
        //最大可创建的线程数
        threadPoolTaskExecutor.setCorePoolSize(threadProperties.getCorePoolSize());
        //队列最大长度
        threadPoolTaskExecutor.setQueueCapacity(threadProperties.getQueueCapacity());
        //线程池维护线程所允许的空闲时间
        threadPoolTaskExecutor.setKeepAliveSeconds(threadProperties.getKeepAliveSeconds());
        //拒绝策略
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return threadPoolTaskExecutor;
    }

    /**
     * 执行周期性或定时性任务
     *
     * @return
     */
    @Bean("scheduledExecutorService")
    public ScheduledExecutorService scheduledExecutorService() {
        BasicThreadFactory build = new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build();
        ThreadPoolExecutor.CallerRunsPolicy callerRunsPolicy = new ThreadPoolExecutor.CallerRunsPolicy();

        ScheduledThreadPoolExecutor scheduledThreadPoolExecutor =
                new ScheduledThreadPoolExecutor(threadProperties.getCorePoolSize(), build, callerRunsPolicy) {
                    @Override
                    protected void afterExecute(Runnable r, Throwable t) {
                        super.afterExecute(r, t);
                        ThreadUtils.printException(r, t);
                    }
                };
        return scheduledThreadPoolExecutor;
    }
}
